package com.britoso.morerecent;

import java.util.HashMap;
import java.util.List;

import android.app.ActivityManager;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

/**
 * The main recent tasks dialog
 * @author britoso
 *
 */
public class RecentDialog extends Dialog implements OnClickListener
{
	Context context;
	int mIconSize = 24;
	RecentData cache;
	boolean DEBUG;

	public RecentDialog(Context context, RecentData cache, final boolean debug)
	{
		super(context);
		this.context = context;
		this.cache = cache;
		this.DEBUG = debug;
	}

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.custom_dialog);
		final Resources resources = context.getResources();
		mIconSize = (int) resources.getDimension(android.R.dimen.app_icon_size);
		long start = System.currentTimeMillis();
		getRecentTasks();
		if (DEBUG)
			Log.i(RecentDialog.class.getName(), "getRecentTasks() took " + (System.currentTimeMillis() - start));
	}

	private static final int NUM_BUTTONS = 15;
	private static final int MAX_RECENT_TASKS = NUM_BUTTONS * 2;
	final View[] mButtons = new View[NUM_BUTTONS];

	private void getRecentTasks()
	{
		long taskFetchTime = System.currentTimeMillis();
		final PackageManager pm = context.getPackageManager();
		final ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

		final List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(MAX_RECENT_TASKS, 0);
		ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), 0);
		taskFetchTime = System.currentTimeMillis() - taskFetchTime;
		int numTasks = recentTasks.size();
		int buttonPos = 0, i = 0;
		long totalButtonCreateTime = 0;
		long totalIconLoadTime = 0;
		long totalIntentResTime = 0;
		long totalLoopTime = System.currentTimeMillis();
		long totalIntentCreationTime = 0;
		long total_activity_title_time = 0;
		long total_checks_time = 0;
		String taskclass = null;
		HashMap<String, ResolveInfo> activityMap = cache.getActivityInfoMap();
		HashMap<String, String> titleMap = cache.getTitleMap();
		HashMap<String, Drawable> iconMap = cache.getIconMap();
		ResolveInfo resolveInfo;
		String title;
		Drawable icon;
		for (; i < numTasks && buttonPos < NUM_BUTTONS; ++i)
		{
			final ActivityManager.RecentTaskInfo task = recentTasks.get(i);
			taskclass = task.baseIntent.getComponent().getClassName();
			long intentCreationTime = System.currentTimeMillis();
			Intent intent = new Intent(task.baseIntent);

			if (task.origActivity != null)
			{
				intent.setComponent(task.origActivity);
			}

			intent.setFlags((intent.getFlags() & ~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
					| Intent.FLAG_ACTIVITY_NEW_TASK);
			intentCreationTime = System.currentTimeMillis() - intentCreationTime;
			totalIntentCreationTime += intentCreationTime;
			long intentResTime = System.currentTimeMillis();
			resolveInfo = null;
			// check the activity cache
			if (activityMap != null)
			{
				resolveInfo = activityMap.get(taskclass);
			}
			if (resolveInfo == null)
			{
				// not found or cache empty
				resolveInfo = pm.resolveActivity(intent, 0);
				activityMap.put(taskclass, resolveInfo);
			}
			intentResTime = System.currentTimeMillis() - intentResTime;
			totalIntentResTime += intentResTime;
			// checks
			if (resolveInfo == null) continue;
			long check_time = System.currentTimeMillis();
			// Skip this activity, or the my downloads activity (no permission)
			if (resolveInfo.activityInfo.packageName.equals(context.getPackageName())
					|| resolveInfo.activityInfo.name.equals("com.android.vending.MyDownloadsActivity")) continue;

			// Skip the current home activity.
			if (homeInfo != null && homeInfo.activityInfo.packageName.equals(resolveInfo.activityInfo.packageName)
					&& homeInfo.activityInfo.name.equals(resolveInfo.activityInfo.name)) continue;
			total_checks_time += (System.currentTimeMillis() - check_time);

			long activity_title_time = System.currentTimeMillis();
			// use title cache
			title = null;
			if (titleMap != null)
			{
				title = titleMap.get(taskclass);
			}
			if (title == null)
			{
				// not found or cache empty
				title = resolveInfo.activityInfo.loadLabel(pm).toString();
				titleMap.put(taskclass, title);
			}
			activity_title_time = System.currentTimeMillis() - activity_title_time;
			total_activity_title_time += activity_title_time;
			long iconLoadTime = System.currentTimeMillis();
			// use icon cache
			icon = null;
			if (iconMap != null)
			{
				icon = iconMap.get(taskclass);
			}
			if (icon == null)
			{
				// not found or cache empty
				icon = resolveInfo.activityInfo.loadIcon(pm);
				iconMap.put(taskclass, icon);
			}
			iconLoadTime = System.currentTimeMillis() - iconLoadTime;
			totalIconLoadTime += iconLoadTime;
			if (DEBUG)
				Log.i(RecentDialog.class.getName(), "Task name: " + title + " Activity="
						+ resolveInfo.activityInfo.name);
			if (title == null || title.length() == 0 || icon == null) continue;
			long buttonCreateTime = System.currentTimeMillis();
			mButtons[buttonPos] = new Button(context);
			View b = mButtons[buttonPos];
			Button bu = (Button) mButtons[buttonPos];
			setButtonAppearance(b, title, icon);
			bu.setBackgroundColor(Color.TRANSPARENT);
			bu.setBackgroundResource(0);
			bu.setTextColor(Color.WHITE);
			b.setTag(intent);
			b.setVisibility(View.VISIBLE);
			b.setPressed(false);
			b.clearFocus();
			buttonPos++;// added a button!
			buttonCreateTime = System.currentTimeMillis() - buttonCreateTime;
			totalButtonCreateTime += buttonCreateTime;
		}
		totalLoopTime = System.currentTimeMillis() - totalLoopTime;
		if (DEBUG)
			Log.i(RecentDialog.class.getName(), "Tasks Fetch Time=" + taskFetchTime + "\nTime to create " + buttonPos
					+ " buttons=" + totalButtonCreateTime + "\nTotal Icon Load time=" + totalIconLoadTime
					+ "\nTotal intent creation time=" + totalIntentCreationTime + "\nTotal Intent Resolution time="
					+ totalIntentResTime + "\nactivity,title time=" + total_activity_title_time + "\ntime for checks="
					+ total_checks_time + "\nTotal loop time=" + totalLoopTime);
		if (buttonPos > 0) createButtonGrid();
		else
			showNotFoundText();
	}

	private void showNotFoundText()
	{
		TableLayout grid = (TableLayout) findViewById(R.id.buttonGrid);
		TableRow row = new TableRow(context);
		TextView t = new TextView(context);
		t.setTextColor(Color.WHITE);
		t.setText(" No Activities Found ");
		t.setTextSize(20);
		t.setVisibility(View.VISIBLE);
		row.addView(t);
		grid.addView(row);
		grid.postInvalidate();
		grid.forceLayout();
		grid.setVisibility(View.VISIBLE);
	}

	/**
	 * Adjust appearance of each icon-button
	 */
	private void setButtonAppearance(View theButton, final String theTitle, final Drawable icon)
	{
		TextView tv = (TextView) theButton;
		tv.setText(theTitle);
		// tv.setBackgroundDrawable()
		if (icon != null)
		{
			icon.setBounds(0, 0, mIconSize, mIconSize);
		}
		tv.setCompoundDrawables(null, icon, null, null);
	}

	// get buttons from mButtons and put it in the grid
	private void createButtonGrid()
	{
		TableLayout grid = (TableLayout) findViewById(R.id.buttonGrid);
		grid.setClipChildren(false);
		int orientation, width, height, numColumns;
		orientation = getWindow().getWindowManager().getDefaultDisplay().getOrientation();
		if (orientation == 0)// portrait
		{
			numColumns = 3;
			width = 95;
			height = 85;
		}
		else // landscape
		{
			numColumns = 5;
			width = 100;
			height = 85;
		}

		int colNum = 0;
		TableRow row = new TableRow(context);
		for (int i = 0; i < mButtons.length && mButtons != null && mButtons[i] != null; i++)
		{
			if (colNum == 0)
			{
				row = new TableRow(context);
			}

			row.addView(mButtons[i], width, height);
			colNum++;
			if (colNum == numColumns || i == mButtons.length - 1 || mButtons[i + 1] == null)
			{
				grid.addView(row);
				grid.postInvalidate();
				grid.forceLayout();
				colNum = 0;
			}
		}

		for (View b : mButtons)
		{
			if (b != null) b.setOnClickListener(this);
		}
		grid.setVisibility(View.VISIBLE);
	}

	/**
	 * Dismiss the recent activities dialog.
	 */
	@Override
	public void onStop()
	{
		super.onStop();

		// dump extra memory we're hanging on to
		for (View b : mButtons)
		{
			if (b == null) continue;
			setButtonAppearance(b, null, null);
			b.setTag(null);
		}
	}

	/**
	 * Handler for user clicks. If a button was clicked, launch the
	 * corresponding activity.
	 */
	public void onClick(View v)
	{

		for (View b : mButtons)
		{
			if (b == v)
			{
				// prepare a launch intent and send it
				Intent intent = (Intent) b.getTag();
				intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
				try
				{
					getContext().startActivity(intent);
				}
				catch (Exception e)
				{
					Log.e(RecentDialog.class.getName(), "Error starting activity: " + e.getMessage());
					e.printStackTrace();
				}
				break;
			}
		}
		dismiss();
	}
}
